﻿using System;
using System.Collections.Generic;
using System.Web.UI;
using System.Web.UI.WebControls;
using Kiiro.Common.Entities;
using Kiiro.Common.Interfaces;
using Kiiro.Common.Utility;
using Kiiro.Model;
using Kiiro.SiteDefinition.ControlTemplates;
using Kiiro.SiteDefinition.Core;
using Kiiro.SiteDefinition.MasterPage;
using Microsoft.SharePoint.Search.Query;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using System.Web;
using Microsoft.SharePoint.Utilities;

using SearchFields = Kiiro.Common.Utility.Constants.SearchFields;

namespace Kiiro.SiteDefinition.ControlTemplates
{
    public partial class SearchResultsControl : System.Web.UI.UserControl
    {

        #region Public Properties

        public BasePage Base
        {
            get { return Page is BasePage ? ( BasePage ) Page : new BasePage ( ).DefaultBasePage; }
        }

        public Pager V2Pager
        {
            get { return (Pager)v2Pager; }
        }

        string webUrl;
        public string WebUrl
        {
            get { return webUrl; }
            set { webUrl = value; }
        }

        string keyword;
        public string Keyword
        {
            get { return keyword; }
            set { keyword = value; }
        }

        string scope;
        public string Scope
        {
            get { return scope; }
            set { scope = value; }
        }

        int start;
        public int Start
        {
            get { return start; }
            set { start = value; }
        }

        #endregion

        #region Private Properties

        Midori midoriIds = new Midori ( );
        Midori midoriSearchResults = new Midori ( );
        Midori categoryMidori = new Midori();

        List<Project> projectNames = new List<Project> ( );

        private int discussionResult = 0;
        private int documentResult = 0;
        private int workResult = 0;
        private int usersResult = 0;
        private int projectsResult = 0;
        private int customListResult = 0;

        #endregion

        private string displayInfo = "<div class='searchresult {0} {1}'><div class='searchresult-body'><h2><a href = '{2}'>{3}</a> </h2>{4}<br/><p>{5}</p></div></div>";

        protected void Page_Load ( object sender, EventArgs e )
        {
            if ( Base.CurrentUser.Groups.Contains ( KiiroGroup.PortalMember ) )
            {
                V2Pager.NextClick += new EventHandler ( RePopulatePage );
                V2Pager.PrevClick += new EventHandler ( RePopulatePage );
                V2Pager.EntitiesPerPageChange += new EventHandler ( RePopulatePage );
                
                Midori midori = SearchModel.Search ( Keyword, Scope, Base.SiteCollectionId, Base.ServerRelativeUrl, Base.CurrentUser );

                //get project names
                if ( SPHelpers.IsPortal ( Base.SiteCollectionId, Base.ServerRelativeUrl ) )
                {
                    projectNames = SearchModel.LookupProjectsNames ( midori, Base.SiteCollectionId, Base.ServerRelativeUrl );
                }

                //Set result count
                projectsResult = midori.Projects.Count;
                usersResult = SPHelpers.IsPortal ( Base.SiteCollectionId, Base.ServerRelativeUrl ) ? midori.Users.Count : midori.TeamMembers.Count;
                workResult = midori.Work.Count;
                discussionResult = midori.Discussions.Count;
                documentResult = midori.Documents.Count;
                customListResult = midori.CustomItems.Count;

                #region Setup Links

                string updateUrl = Request.RawUrl;
                updateUrl = SPHelpers.EditQueryString ( updateUrl, "page", null );
                lnkAll.NavigateUrl = SPHelpers.EditQueryString ( updateUrl, "Category", "All" );
                lnkWork.NavigateUrl = SPHelpers.EditQueryString ( updateUrl, "Category", "Work" );
                lnkDocuments.NavigateUrl = SPHelpers.EditQueryString ( updateUrl, "Category", "Documents" );
                lnkDiscussions.NavigateUrl = SPHelpers.EditQueryString ( updateUrl, "Category", "Discussions" );
                lnkUsers.NavigateUrl = SPHelpers.EditQueryString ( updateUrl, "Category", "Users" );
                lnkProjects.NavigateUrl = SPHelpers.EditQueryString ( updateUrl, "Category", "Projects" );
                lnkLists.NavigateUrl = SPHelpers.EditQueryString ( updateUrl, "Category", "Lists" );

                #endregion

                if ( !string.IsNullOrEmpty ( Keyword ) )
                {
                    categoryMidori = new Midori ( );
                    midoriSearchResults = midori;

                    //Check url is search is filtered by category
                    #region Category Filter

                    if ( Request.Url.ToString ( ).ToLower ( ).Contains ( "&category=all" ) || !Request.Url.ToString ( ).ToLower ( ).Contains ( "&category" ) )
                    {
                        categoryMidori = midoriSearchResults;
                    }
                    else if ( Request.Url.ToString ( ).ToLower ( ).Contains ( "&category=work" ) )
                    {
                        categoryMidori.Work = midoriSearchResults.Work;
                    }
                    else if ( Request.Url.ToString ( ).ToLower ( ).Contains ( "&category=documents" ) )
                    {
                        categoryMidori.Documents = midoriSearchResults.Documents;
                    }
                    else if ( Request.Url.ToString ( ).ToLower ( ).Contains ( "&category=discussions" ) )
                    {
                        categoryMidori.Discussions = midoriSearchResults.Discussions;
                    }
                    else if ( Request.Url.ToString ( ).ToLower ( ).Contains ( "&category=users" ) )
                    {
                        if ( SPHelpers.IsPortal ( Base.SiteCollectionId, Base.ServerRelativeUrl ) )
                            categoryMidori.Users = midoriSearchResults.Users;
                        else
                            categoryMidori.TeamMembers = midoriSearchResults.TeamMembers;
                    }
                    else if ( Request.Url.ToString ( ).ToLower ( ).Contains ( "&category=projects" ) )
                    {
                        categoryMidori.Projects = midoriSearchResults.Projects;
                    }
                    else if ( Request.Url.ToString ( ).ToLower ( ).Contains ( "&category=lists" ) )
                    {
                        categoryMidori.CustomItems = midoriSearchResults.CustomItems;
                    }

                    #endregion

                    lblSearchTerm.Text = Keyword;
                    DisplayMidoriEntities ( categoryMidori );
                }
                else
                {
                    searchContent.Attributes.Add ( "class", "panel-content" );
                    v2Pager.Visible = false;
                    resultsData.Text = DisplayNoKeyword ( );
                }
            }
        }

        private void DisplayMidoriEntities ( Midori midori )
        {
            List<BaseEntity> baseEntities = midori.AllEntities ( );

            string display = "";
            string lastRow = "";

            if ( baseEntities != null && baseEntities.Count > 0 )
            {
                V2Pager.PopulatePager(baseEntities.Count, Constants.PagerEntity.SearchResults);
                

                int count = baseEntities.Count - 1;
                int lastDisplayed = 1;
                foreach ( BaseEntity entity in baseEntities.GetRange(V2Pager.PagingIndex,V2Pager.DisplayedCount) )
                {
                    if (lastDisplayed == V2Pager.DisplayedCount)
                    {
                        lastRow = "borderless";
                    }
                    lastDisplayed++;

                    string fromProject = "";
                    string formattedUrl = "";
                    string urlPrefix = "";                    
                    switch ( entity.GetType ( ).Name )
                    {
                        case "Project":
                            Project project = ( Project ) entity;
                            display += String.Format ( displayInfo, "label-project", lastRow, project.ServerRelativeWebUrl, SPHelpers.ConvertHtmlToKiiroSafeText ( project.Title ), "", SPHelpers.ConvertHtmlToKiiroSafeText ( project.SummaryNote ) );
                            break;

                        case "User":
                            User user = ( User ) entity;
                            formattedUrl = string.Format("{0}{1}?id={2}", SPHelpers.GetPortalServerRelativeUrl(Base.SiteCollectionId, Base.ServerRelativeUrl), Constants.PortalFileUrls.UserDisplay, user.SPUserId);
                            display += String.Format ( displayInfo, "label-user", lastRow, formattedUrl, SPHelpers.ConvertHtmlToKiiroSafeText ( user.FullName ), "", SPHelpers.ConvertHtmlToKiiroSafeText ( user.StatusNote ) );
                            break;

                        case "TeamMember":
                            TeamMember member = ( TeamMember ) entity;
                            user = member.User;                            
                            urlPrefix = SPHelpers.GetServerRelativeWebUrl(member.SiteCollectionId, member.ServerRelativeUrl);
                            formattedUrl = string.Format ( "{0}{1}?id={2}", urlPrefix, Constants.PortalFileUrls.UserDisplay, user.SPUserId );
                            display += String.Format ( displayInfo, "label-user", lastRow, formattedUrl, SPHelpers.ConvertHtmlToKiiroSafeText ( user.FullName ), "", SPHelpers.ConvertHtmlToKiiroSafeText ( user.StatusNote ) );
                            break;

                        case "Work":
                            Work work = ( Work ) entity;                            

                            urlPrefix = SPHelpers.GetServerRelativeWebUrl(work.SiteCollectionId, work.ServerRelativeUrl);

                            if ( projectNames != null && projectNames.Count > 0 )
                            {
                                Project projectName = projectNames.Find ( x => work.ServerRelativeUrl.Contains ( x.ServerRelativeWebUrl ) );
                                fromProject = projectName != null ? string.Format ( " from <a href='{0}'>{1}</a>", urlPrefix, SPHelpers.ConvertHtmlToKiiroSafeText ( projectName.Title ) ) : string.Empty;
                            }

                            string workUrl = work.WorkItemType == WorkType.Task ? Constants.ProjectFileUrls.TaskDisplay : Constants.ProjectFileUrls.IssueDisplay;
                            string label = work.WorkItemType == WorkType.Task ? "label-task" : "label-issue";

                            formattedUrl = string.Format("{0}{1}?id={2}", urlPrefix, workUrl, work.Id);
                            display += String.Format ( displayInfo, label, lastRow, formattedUrl, SPHelpers.ConvertHtmlToKiiroSafeText ( work.Title ), fromProject, SPHelpers.ConvertHtmlToKiiroSafeText ( work.Description ) );
                            break;

                        case "Discussion":
                            Discussion discussion = ( Discussion ) entity;
                            urlPrefix = SPHelpers.GetServerRelativeWebUrl(discussion.SiteCollectionId, discussion.ServerRelativeUrl);

                            if ( projectNames != null && projectNames.Count > 0 )
                            {
                                Project projectName = projectNames.Find ( x => discussion.ServerRelativeUrl.Contains ( x.ServerRelativeWebUrl ) );
                                fromProject = projectName != null ? string.Format ( " from <a href='{0}'>{1}</a>", urlPrefix, SPHelpers.ConvertHtmlToKiiroSafeText ( projectName.Title ) ) : string.Empty;
                            }
                            
                            formattedUrl = string.Format ( "{0}{1}?id={2}", urlPrefix, Constants.ProjectFileUrls.DiscussionDisplay, discussion.Id );
                            display += String.Format ( displayInfo, "label-discussion", lastRow, formattedUrl, SPHelpers.ConvertHtmlToKiiroSafeText ( discussion.Title ), fromProject, SPHelpers.ConvertHtmlToKiiroSafeText ( discussion.Text ) );
                            break;

                        case "Document":
                            Document document = ( Document ) entity;
                            
                            urlPrefix = SPHelpers.GetServerRelativeWebUrl(document.SiteCollectionId, document.ServerRelativeUrl);

                            if ( projectNames != null && projectNames.Count > 0 )
                            {
                                Project projectName = projectNames.Find ( x => document.ServerRelativeUrl.Contains ( x.ServerRelativeWebUrl ) );
                                fromProject = projectName != null ? string.Format ( " from <a href='{0}'>{1}</a>", urlPrefix, SPHelpers.ConvertHtmlToKiiroSafeText ( projectName.Title ) ) : string.Empty;
                            }

                            display += String.Format ( displayInfo, "label-document", lastRow, document.ServerRelativeUrl, SPHelpers.ConvertHtmlToKiiroSafeText ( document.Title ), fromProject, SPHelpers.ConvertHtmlToKiiroSafeText ( document.Description ) );
                            break;

                        case "CustomItem":
                            CustomItem customItem = ( CustomItem ) entity;
                            urlPrefix = SPHelpers.GetServerRelativeWebUrl(customItem.SiteCollectionId, customItem.ServerRelativeUrl);

                            if (projectNames != null && projectNames.Count > 0)
                            {
                                Project projectName = projectNames.Find(x => customItem.ServerRelativeUrl.Contains(x.ServerRelativeWebUrl));
                                fromProject = projectName != null ? string.Format ( " from <a href='{0}'>{1}</a>", urlPrefix, SPHelpers.ConvertHtmlToKiiroSafeText ( projectName.Title ) ) : string.Empty;
                            }

                            display += String.Format ( displayInfo, "label-list", lastRow, customItem.Url, SPHelpers.ConvertHtmlToKiiroSafeText ( customItem.Title ), fromProject, SPHelpers.ConvertHtmlToKiiroSafeText ( customItem.Description ) );
                            break;

                        default:
                            break;
                    }
                }
                SetResultsCount ( discussionResult, documentResult, usersResult, workResult, projectsResult, customListResult );
            }
            else
            {
                searchContent.Attributes.Add("class", "panel-content");
                v2Pager.Visible = false;
                display = DisplayNoResults ( );
            }

            resultsData.Text = display;
        }
        
        /// <summary>
        /// Rendering pattern for search summary bar at top and bottom of result set
        /// </summary>
        /// <param name="start">starting result number</param>
        /// <param name="rowCount">number of rows (results returned)</param>
        /// <param name="totalRows">total number of rows (results)</param>
        /// <param name="elapsedTime">total search time</param>
        /// <returns></returns>
        private string DisplaySearchSummary ( int start, int rowCount, int totalRows, int elapsedTime )
        {
            //Results 1-10 of 13. Your search took 0.16 seconds.
            return "<div id='SRST' class='srch-WPBody'>" +
                        "<div class='srch-stats'>" +
                //"Results <b>" + Convert.ToString ( start ) + "-" + Convert.ToString ( rowCount ) + "</b> of " + Convert.ToString ( totalRows ) + "." +
                            "&nbsp;Your search took 0." + Convert.ToString ( elapsedTime ) + " seconds." +
                        "</div>" +
                    "</div>";
        }

        /// <summary>
        /// Rendering patteren for no keyword/search term
        /// </summary>
        /// <returns></returns>
        private string DisplayNoKeyword ( )
        {
            SetResultsCount ( 0, 0, 0, 0, 0, 0 );
            return @"
                <span class=""settings"">
			        Enter one or more words to search for in the search box.
    		    </span>";
        }

        /// <summary>
        /// Rendering pattern for no results
        /// </summary>
        /// <returns></returns>
        private string DisplayNoResults ( )
        {
            SetResultsCount ( 0, 0, 0, 0, 0, 0 );
            return @"
		        <div class="""" id=""CSR_NO_RESULTS"">
                    <div class=""searchresult-body settings"">
			        No results matching your search were found.
                    <ol>
				        <li>Check your spelling. Are the words in your query spelled correctly?</li>
				        <li>Try using synonyms. Maybe what you're looking for uses slightly different words.</li>
				        <li>Make your search more general. Try more general terms in place of specific ones.</li>
				        <li>Try your search in a different scope. Different scopes can return different results.</li>
			        </ol>
                    </div> 
		        </div>";
        }

        /// <summary>
        /// Rendering pattern for noise keywords (the, and, is, etc.)
        /// </summary>
        /// <param name="ex"></param>
        /// <returns></returns>
        private string DisplayOnlyNoiseWords ( AllNoiseQueryException ex )
        {
            return DisplaySharePointErrorMessage ( ex );
        }

        /// <summary>
        /// Rendering pattern for SharePoint Keyord Word Exception messages 
        /// </summary>
        /// <param name="ex"></param>
        /// <returns></returns>
        private string DisplaySharePointErrorMessage ( Exception ex )
        {
            SetResultsCount ( 0, 0, 0, 0, 0, 0 );
            return @"
                <span class=""settings"">" +
                    ex.Message +
                "</span>";
        }
        
        private void SetResultsCount ( int discussionResult, int documentResult, int usersResult, int workResult, int projectsResult, int customListResult )
        {
            allCount.Text = "( " + ( discussionResult + documentResult + usersResult + workResult + projectsResult + customListResult  ).ToString ( ) + " ) ";
            discussionsCount.Text = "( " + discussionResult.ToString ( ) + " ) ";
            workCount.Text = "( " + workResult.ToString ( ) + " ) ";
            usersCount.Text = "( " + usersResult.ToString ( ) + " ) ";
            documentsCount.Text = "( " + documentResult.ToString ( ) + " ) ";
            listsCount.Text = "( " + customListResult.ToString() + " )";
            
            bool isPortal = SPHelpers.IsPortal ( Base.SiteCollectionId, Base.ServerRelativeUrl );
            projectsCount.Text = isPortal ? "( " + projectsResult.ToString ( ) + " ) " : string.Empty;
            projectsCount.Visible = isPortal;
            lnkProjects.Visible = isPortal;
            liProjects.Visible = isPortal;
            
            lnkAll.Enabled = ( discussionResult + documentResult + usersResult + workResult + projectsResult ) > 0;
            lnkAll.CssClass += lnkAll.Enabled ? "" : " disabled";
            lnkDocuments.Enabled = documentResult > 0;
            lnkDocuments.CssClass += lnkDocuments.Enabled ? "" : " disabled";
            lnkLists.Enabled = customListResult > 0;
            lnkLists.CssClass += lnkLists.Enabled ? "" : " disabled";
            lnkUsers.Enabled = usersResult > 0;
            lnkUsers.CssClass += lnkUsers.Enabled ? "" : " disabled";
            lnkWork.Enabled = workResult > 0;
            lnkWork.CssClass += lnkWork.Enabled ? "" : " disabled";
            lnkDiscussions.Enabled = discussionResult > 0;
            lnkDiscussions.CssClass += lnkDiscussions.Enabled ? "" : " disabled";
            lnkProjects.Enabled = projectsResult > 0;
            lnkProjects.CssClass += lnkProjects.Enabled ? "" : " disabled";            
        }


        #region Pager Related Methods

        private void RePopulatePage(object sender, EventArgs e)
        {
            DisplayMidoriEntities(categoryMidori);
        }

        protected void SortBy_Click(object sender, EventArgs e)
        {
            LinkButton link = (LinkButton)sender;
            if (V2Pager.SortDirection == System.Web.UI.WebControls.SortDirection.Ascending && V2Pager.SortExpression == link.CommandArgument)
                V2Pager.SortDirection = System.Web.UI.WebControls.SortDirection.Descending;
            else
                V2Pager.SortDirection = System.Web.UI.WebControls.SortDirection.Ascending;
            V2Pager.SortExpression = link.CommandArgument;

            DisplayMidoriEntities(categoryMidori);
        }

        #endregion
    }
}

/*************************************************************************
 * 
 * $Log: /Internal Projects/Kiiro/Kiiro.SiteDefinition/12/TEMPLATE/CONTROLTEMPLATES/Kiiro/SearchResultsControl.ascx.cs $
 * 
 * 15    2/08/10 5:04p Camerons
 * 
 * 14    1/25/10 1:17p Camerons
 * 
 * 13    1/12/10 12:03p Camerons
 * 
 * 12    26/11/09 10:35a Camerons
 * 
 * 11    17/11/09 6:46p Camerons
 * 
 * 10    6/11/09 7:34p Camerons
 * 
 * 9     10/26/09 10:00a Adamw
 * Case 348
 * 
 * 8     30/09/09 4:08p Camerons
 * Update all links that point to UserPages, pass User.SPUserId as the
 * ItemId so that we can safely run GetOrCreateUser
 * 
 * 7     22/09/09 6:03p Camerons
 * Code changes to support creating user on demand - version 1.1.x.x
 * 
 * 6     22/09/09 9:58a Shafia
 * Implemented New Pager
 * 
 * 5     17/08/09 11:07a Camerons
 * Added check-in comments section
 * 
 ************************************************************************/